package com.hotel.tv.application.admin.services.emp.impl;

import com.autumn.application.dto.input.AdvancedPageQueryInput;
import com.autumn.application.dto.input.AdvancedSearchInput;
import com.autumn.cloud.uid.UID;
import com.autumn.cloud.uid.UidGenerator;
import com.autumn.exception.ExceptionUtils;
import com.autumn.file.storage.StorageClient;
import com.autumn.mybatis.mapper.PageResult;
import com.autumn.mybatis.wrapper.EntityQueryWrapper;
import com.autumn.mybatis.wrapper.LockModeEnum;
import com.autumn.util.StringUtils;
import com.autumn.zero.common.library.application.services.common.CommonDataDictionaryAppService;
import com.autumn.zero.file.storage.application.services.AbstractZeroFileUploadEditAppService;
import com.hotel.tv.application.admin.dto.emp.*;
import com.hotel.tv.application.admin.services.emp.EmpInfoAppService;
import com.hotel.tv.constants.CommonDictionaryTypeConstant;
import com.hotel.tv.constants.FileUploadAttachmentTypeConstant;
import com.hotel.tv.entities.emp.EmpInfo;
import com.hotel.tv.entities.emp.query.EmpInfoQuery;
import com.hotel.tv.repositories.emp.EmpInfoRepository;
import com.hotel.tv.repositories.emp.query.EmpInfoQueryRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Set;

/**
 * <p>
 * </p>
 *
 * @description TODO
 * @author: 老码农
 * @create: 2020-04-08 15:24
 **/
@Service
public class EmpInfoAppServiceImpl extends AbstractZeroFileUploadEditAppService<
        EmpInfo,
        EmpInfoRepository,
        EmpInfoQuery,
        EmpInfoQueryRepository, EmpInfoInput, EmpInfoInput, EmpInfoListOutput, EmpInfoDetailsOutput>
        implements EmpInfoAppService {

    private final CommonDataDictionaryAppService dataDictionaryAppService;
    private final StorageClient storageClient;

    public EmpInfoAppServiceImpl(CommonDataDictionaryAppService dataDictionaryAppService,
                                 StorageClient storageClient) {
        this.dataDictionaryAppService = dataDictionaryAppService;
        this.storageClient = storageClient;
        this.getSearchMembers().add("empCode");
        this.getSearchMembers().add("empName");
        this.getSearchMembers().add("postName");
        this.getSearchMembers().add("roleName");
    }

    @Override
    public String getModuleName() {
        return "员工管理";
    }

    @Autowired
    private UidGenerator generator;

    /**
     * 消息置顶
     */
    public void msgTop() {
        UID uid = generator.newUID();
        //最新的uid，一定会比之前的大
        Long newId = uid.getUid();
        //update
        //还可以反向解析
        UID old = generator.parseUID(newId);
        //工作id，哪台机器分配的
        //old.getWorkerId()
        //顺序号
        //old.getSequence()
        //起步秒数(1970-1-1)开始
        //old.getEpochSeconds()
        //周期秒数   与起步间隔
        //old.getDeltaSeconds()
        //时间戳
        //old.getTimestamp()
    }

    private void checkEdit(EmpInfoInput input, boolean checkEmpCode) {
        if (!dataDictionaryAppService.existEnableDictionary(CommonDictionaryTypeConstant.POST, input.getPostId())) {
            ExceptionUtils.throwValidationException("职务id无效，不存在或已停用的职务");
        }
        if (!dataDictionaryAppService.existEnableDictionary(CommonDictionaryTypeConstant.ROLE, input.getRoleId())) {
            ExceptionUtils.throwValidationException("岗位id无效，不存在或已停用的岗位");
        }
        if (checkEmpCode) {
            EntityQueryWrapper<EmpInfo> wrapper = new EntityQueryWrapper<>(EmpInfo.class);


           // wrapper.where().eq("empCode",input.getEmpCode().trim());


            wrapper.lambda()
                    .where().eq(EmpInfo::getEmpCode, input.getEmpCode().trim());
            wrapper.lockByUpdate();
            if (this.getRepository().countByWhere(wrapper) > 0) {
                ExceptionUtils.throwValidationException("员工编号[" + input.getEmpCode() + "]已存在。");
            }
        }
    }

    @Override
    protected EmpInfo addBefore(EmpInfoInput input, EntityQueryWrapper<EmpInfo> query) {
        this.checkEdit(input, true);
        return super.addBefore(input, query);
    }

    @Override
    protected void updateBefore(EmpInfoInput input, EmpInfo entity, EntityQueryWrapper<EmpInfo> wrapper) {
        boolean checkEmpCode = !entity.getEmpCode().equalsIgnoreCase(input.getEmpCode().trim());
        this.checkEdit(input, checkEmpCode);
        super.updateBefore(input, entity, wrapper);
    }

    @Override
    public int getFileUploadAttachmentType() {
        return FileUploadAttachmentTypeConstant.EMP_INFO;
    }

    @Override
    public String getFileUploadStartPath() {
        return "emp/info";
    }

    @Override
    public Set<String> getFileUploadLimitExtensions() {
        return null;
    }

    @Override
    public Long getFileUploadLimitSize() {
        return null;
    }

    @Override
    protected void itemConvertHandle(EmpInfoQuery source, EmpInfoListOutput target) {
        if (StringUtils.isNotNullOrBlank(source.getHeadPath())) {
            target.setHeadPath(storageClient.getAccessUrl(this.storageClient.getDefaultBucketName(), source.getHeadPath()));
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void deleteOrder(Long orderNo) {

        //select * from a where ... 1
        //select * from a where ... 3
        //select * from a where ... 4
        //select * from a where ... 4
        //update .... 1
        //update .... 2
        //update .... 3

        //select * from user_info where id = 1 for update

        EmpInfo info = this.getRepository().getByLock(orderNo, LockModeEnum.UPDATE);
        if (info.getPostId() == 1) {
            //update .... 1
        } else {
            //update .... 2
        }

    }

    @Override
    protected EmpInfoDetailsOutput toOutputByQuery(EmpInfoQuery empInfoQuery) {
        EmpInfoDetailsOutput result = super.toOutputByQuery(empInfoQuery);
        if (result != null) {
            if (StringUtils.isNotNullOrBlank(result.getHeadPath())) {
                result.setHeadPath(storageClient.getAccessUrl(this.storageClient.getDefaultBucketName(), result.getHeadPath()));
            }
            /*if(result.getHeadUploadFile()!=null){
                result.setHeadPath(result.getHeadUploadFile().getAccessUrlPath());
            }*/
        }
        return result;
    }

    @Override
    protected void queryInputCriteria(EntityQueryWrapper<EmpInfoQuery> query, AdvancedSearchInput input) {
        super.queryInputCriteria(query, input);
        if (input instanceof EmpAdvancedPageQueryInput) {
            EmpAdvancedPageQueryInput queryInput = (EmpAdvancedPageQueryInput) input;
            if (queryInput.getQueryType() == 10) {
                query.lambda().where().eq(EmpInfoQuery::getEmpCode, "005");
            }
        }
    }

    @Override
    public PageResult<EmpInfoListOutput> queryForPage(AdvancedPageQueryInput input) {
        return super.queryForPage(input);
    }

    @Override
    public PageResult<EmpInfoListOutput> queryForCusPage(EmpCusAdvancedPageQueryInput input) {
        if (input == null) {
            input = new EmpCusAdvancedPageQueryInput();
        }
        /*PageQueryBuilder<EmpInfoQuery> queryBuilder = new PageQueryBuilder<>(this.getQueryEntityClass());
        this.generateQueryListColumn(queryBuilder.getQuery());
        this.systemByCriteria(queryBuilder.getQuery());
        this.queryByOrder(queryBuilder.getQuery());

        queryBuilder.page(input.getCurrentPage(), input.getPageSize());

        if (StringUtils.isNotNullOrBlank(input.getEmpCode())) {
            queryBuilder.getQuery().lambda().where().eq(EmpInfoQuery::getEmpCode, input.getEmpCode().trim());
        }

        if (StringUtils.isNotNullOrBlank(input.getEmpName())) {
            queryBuilder.getQuery().lambda().where().eq(EmpInfoQuery::getEmpName, input.getEmpName().trim());
        }
         return queryBuilder.toPageResult(getQueryRepository(), this.getOutputItemClass(), this::itemConvertHandle);
        */

        EntityQueryWrapper<EmpInfoQuery> wrapper = new EntityQueryWrapper<>(EmpInfoQuery.class);
        wrapper.page(input.getCurrentPage(), input.getPageSize());
        if (StringUtils.isNotNullOrBlank(input.getEmpCode())) {
            wrapper.lambda().where().eq(EmpInfoQuery::getEmpCode, input.getEmpCode().trim());
        }
        if (StringUtils.isNotNullOrBlank(input.getEmpName())) {
            wrapper.lambda().where().eq(EmpInfoQuery::getEmpName, input.getEmpName().trim());
        }
        wrapper.lambda().orderBy(EmpInfoQuery::getEmpCode);
        return getQueryRepository().selectForPageConvertAction(wrapper, EmpInfoListOutput.class, (s, t) -> {
            this.itemConvertHandle(s, t);
        });
    }
}
